<template>
  <el-card shadow="always">
    <!-- 头部：面包屑 -->
    <div slot="header">
      <el-breadcrumb separator-class="el-icon-arrow-right">
        <el-breadcrumb-item to="/">首页</el-breadcrumb-item>

        <!-- 通过 template 编组，通过一个 v-if 控制多个标签的条件渲染 -->
        <template v-if="$route.params.id">
          <el-breadcrumb-item to="/article">内容管理</el-breadcrumb-item>
          <el-breadcrumb-item>修改文章</el-breadcrumb-item>
        </template>

        <el-breadcrumb-item v-else>发布文章</el-breadcrumb-item>

      </el-breadcrumb>
    </div>

    <!-- 主体：表单 -->
    <el-form ref="formRef" label-width="120px" :model="articleForm" :rules="articleRules">
      <el-form-item label="标题：" prop="title">
        <el-input v-model="articleForm.title" placeholder="请输入文章标题" style="width: 400px"></el-input>
      </el-form-item>

      <el-form-item label="频道：" prop="channel_id">
        <!-- 频道组件(全局组件) -->
        <geek-channel v-model="articleForm.channel_id" />
      </el-form-item>

      <el-form-item label="封面：" prop="cover">
        <el-radio-group @change="changeCoverType()" v-model="articleForm.cover.type">
          <el-radio :label="1">单图</el-radio>
          <el-radio :label="3">三图</el-radio>
          <el-radio :label="0">无图</el-radio>
          <el-radio :label="-1">自动</el-radio>
        </el-radio-group>
        <div v-if="articleForm.cover.type === 1 || articleForm.cover.type === 3">
          <!--
            el-upload 上传组件参数
              action        必选参数，上传的地址
              list-type     文件列表的类型 text(文本) / picture(图片) / picture-card(图片墙)
              http-request  覆盖默认的上传行为，可以自定义上传的实现
              on-remove     文件列表移除文件时的钩子
          -->
          <el-upload ref="uploadRef" action="" list-type="picture-card" :http-request="uploadFile"
            :limit="articleForm.cover.type" :on-remove="removeFile" :file-list="fileList">
            <i class="el-icon-plus"></i>
          </el-upload>
        </div>
      </el-form-item>

      <el-form-item label="内容：" prop="content">
        <div class="editor">
          <!-- 4. 使用富文本组件，通过 v-model 收集数据 -->
          <quillEditor @blur="checkContent()" v-model="articleForm.content" />
        </div>
      </el-form-item>
      <el-form-item label="" v-if="$route.params.id">
        <el-button @click="onEdit(false)" type="primary">修改文章</el-button>
        <el-button @click="onEdit(true)">存入草稿</el-button>
      </el-form-item>
      <el-form-item label="" v-else>
        <el-button @click="onSubmit(false)" type="primary">发表文章</el-button>
        <el-button @click="onSubmit(true)">存入草稿</el-button>
        {{ articleForm }}
      </el-form-item>

    </el-form>
  </el-card>
</template>

<script>
// 1. 导入富文本样式
import 'quill/dist/quill.core.css'
import 'quill/dist/quill.snow.css'
import 'quill/dist/quill.bubble.css'

// 2. 导入富文本组件
import { quillEditor } from 'vue-quill-editor'

export default {
  name: 'PublishView',
  // 3. 注册组件
  components: {
    quillEditor
  },
  data () {
    // 自定义校验函数
    const checkCoverFn = (_, cover, callback) => {
      if (cover.type === 1 && cover.images.length < 1) {
        return callback(new Error('请上传一张封面'))
      } else if (cover.type === 3 && cover.images.length < 3) {
        return callback(new Error('请上传三张封面'))
      }
      // 通过校验
      callback()
    }
    return {
      articleForm: {
        title: '', // 文章标题
        content: '', // 文章内容
        cover: {
          type: 1, // 封面类型 -1:自动，0-无图，1-1张，3-3张
          images: [] // 封面图片数组
        },
        channel_id: 0 // 文章所属频道id
      },
      // 校验规则
      articleRules: {
        title: [
          { required: true, message: '请输入文章标题', trigger: 'blur' },
          { min: 4, max: 50, message: '文章标题4-50字符', trigger: 'blur' }
        ],
        channel_id: [
          { required: true, message: '请选择文章频道', trigger: 'change' }
        ],
        content: [
          { required: true, message: '请输入文章内容', trigger: 'blur' }
        ],
        cover: [
          { validator: checkCoverFn, trigger: 'change' }
        ]
      }
    }
  },
  // 通过计算属性，缓存图片列表
  computed: {
    fileList () {
      return this.articleForm.cover.images.map(item => ({ name: item, url: item, response: item }))
    }
  },
  created () {
    // 如果路由中有 id 参数，则表示为编辑文章，发送请求获取文章详情
    if (this.$route.params.id) {
      this.getArticle()
    }
  },
  // 组件内的路由导航守卫（只在组件被复用时触发，不会跟 created 冲突）
  beforeRouteUpdate (to, from, next) {
    // 判断是否有 id 变化
    if (to.params.id) {
      // 举例： /publish/:id?，在 /publish/1 和 /publish/2 之间跳转的时候
      this.getArticle()
    } else {
      // 举例：/publish/1 跳转到 /publish
      // 如果没有 id，则为发布文章页，清空表单(包括内容和校验信息)
      this.$refs.formRef.resetFields()
    }
    next()
  },
  methods: {
    // 获取文章详情
    async getArticle () {
      try {
        const res = await this.$http.get(`/v1_0/mp/articles/${this.$route.params.id}`)
        // console.log(res)
        this.articleForm = res.data.data
      } catch (error) {
        // 1. 提示用户文章不存在
        this.$message.error('文章不存在')
        // 2. 跳转文章管理页
        this.$router.push('/article')
      }
    },
    // 上传组件的删除文件
    removeFile (file) {
      // console.log('被删除的文件信息', file)
      this.articleForm.cover.images = this.articleForm.cover.images.filter(v => v !== file.response)
      // 主动触发 cover 校验
      this.$refs.formRef.validateField('cover')
    },
    // 覆盖默认的上传行为，可以自定义上传的实现
    async uploadFile (obj) {
      // console.log('上传', obj)
      // 创建 FormData 对象，用于上传图片
      const fd = new FormData()
      // 注意：后端接口文档的字段要求
      fd.append('image', obj.file)
      // 发送请求，上传文件
      const res = await this.$http.post('/v1_0/upload', fd)
      // console.log(res)
      // 将图片地址添加到数组中
      this.articleForm.cover.images.push(res.data.data.url)
      // 主动触发 cover 校验
      this.$refs.formRef.validateField('cover')
      // 添加返回值，返回的图片地址会被记录到到文件的 response 属性上
      return res.data.data.url
    },
    changeCoverType () {
      // 清空已上传的文件列表
      this.$refs.uploadRef?.clearFiles()
      // 清空封面数组
      this.articleForm.cover.images = []
    },
    // 富文本组件失去焦点
    checkContent () {
      // .validateField()  单独校验某个字段的值
      this.$refs.formRef.validateField('content')
    },
    // 发表文本和存草稿，是否存为草稿，true是 false否
    onSubmit (draft) {
      // 整个表单校验
      this.$refs.formRef.validate(async (res) => {
        if (res) {
          await this.$http.post('/v1_0/mp/articles', this.articleForm, { params: { draft } })
          this.$message.success(draft ? '草稿保存成功' : '发表成功')
          this.$router.push('/article')
        }
      })
    },
    onEdit (draft) {
      // 整个表单校验
      this.$refs.formRef.validate(async (res) => {
        if (res) {
          await this.$http.put(`/v1_0/mp/articles/${this.$route.params.id}`, this.articleForm, { params: { draft } })
          this.$message.success(draft ? '草稿保存成功' : '修改成功')
        }
      })
    }
  }
}
</script>

<style scoped>
/* ::v-deep 本质就是 [data-v-xxx] 属性，我们可以调整默认位置到前面，实现样式穿透，深度选择器 */
::v-deep .ql-editor {
  min-height: 300px;
}

/* 关闭上传组件的动画效果 */
::v-deep .el-upload-list__item {
  transition: none;
}
</style>
